﻿using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Utils.ControlToLoad;
using Utils.Web;
using Core;
using Utils.Exceptions;
using System.Collections.Generic;
using Core.DAL;
using System.Transactions;

namespace xManagerWebApp
{
    public partial class ControlExpenseLine : ControlWithDDlAndId
    {
        private const String DDL_FIRST_ELEM = "Select...";

        protected void Page_Load(object sender, EventArgs e)
        {
            //ExpenseLine l = ExpenseLine.Get(new Guid("23b58779-486d-43b7-a3b9-aa43b031fa83"));

            //this.ControlId = new Guid("23b58779-486d-43b7-a3b9-aa43b031fa83");
            //this.ReadOnly = true;

            if (!this.ReadOnly)
                this.LoadIfNotReadOnly();
            this.LoadEditControls();
        }

        private void LoadEditControls()
        {
            using (DataAccessLayer dal = new DataAccessLayer())
            {
                IEnumerator templates = Template.GetAll(dal).GetEnumerator();
                while (templates.MoveNext())
                {
                    String controlName = ((Template)(templates.Current)).EditControl;
                    Control c = Page.LoadControl(this.BuildSelectedControlString(controlName));
                    this.ph_ControlHolder.Controls.Add(c);
                }
            }
        }

        private void LoadIfNotReadOnly()
        {
            if (!IsPostBack)
                this.Bind_ddl_ExpenseTypes();
        }

        private void LoadIfReadOnly()
        {

        }

        public Guid? ExpenseReportId
        {
            get
            {
                if (ViewState["ExpenseReportId"] != null)
                    return (Guid)ViewState["ExpenseReportId"];
                else
                    return null;
            }
            set { ViewState["ExpenseReportId"] = value; }
        }

        public bool ReadOnly
        {
            get
            {
                if (ViewState["ReadOnly"] != null)
                    return (bool)ViewState["ReadOnly"];
                else
                    return false;
            }
            set { ViewState["ReadOnly"] = value; }
        }

        public bool FirstAccess
        {
            get
            {
                if (ViewState["FirstAccess"] != null)
                    return (bool)ViewState["FirstAccess"];
                else
                    return false;
            }
            set { ViewState["FirstAccess"] = value; }
        }

        //id do expenseType seleccionado
        public Guid? TypeId
        {
            get
            {
                if (ViewState["TypeId"] != null)
                    return (Guid)ViewState["TypeId"];
                else
                    return null;
            }
            set { ViewState["TypeId"] = value; }
        }
        private void Bind_ddl_ExpenseTypes()
        {
            using (DataAccessLayer dal = new DataAccessLayer())
            {
                this.ddl_ExpenseTypes.DataSource = ExpenseType.GetAll(dal);
                this.ddl_ExpenseTypes.DataBind();
                this.ddl_ExpenseTypes.Items.Insert(0, DDL_FIRST_ELEM);
            }
        }

        private void LoadFields(ExpenseLine el)
        {

            this.tb_Date.Text = el.Date.Value.Date.ToShortDateString();
            this.tb_description.Text = el.Description;
            this.tb_Justification.Text = el.Justification;
        }

        private void ClearFields()
        {
            this.tb_description.Text = string.Empty;
            this.tb_Justification.Text = string.Empty;
            this.tb_Date.Text = string.Empty;
            this.ddl_ExpenseTypes.SelectedIndex = 0;
        }

        public override void DataBind()
        {
            base.DataBind();

            if (!this.InstanceId.HasValue)
            {
                if (Context.Items["ToClear"] != null)
                {
                    if (Context.Items["ToClear"].Equals("true"))
                    {
                        this.ClearFields();
                        this.ph_ControlHolder.Controls.Clear();
                    }
                }
                return;
            }
            using (DataAccessLayer dal = new DataAccessLayer())
            {
                ExpenseLine el = ExpenseLine.Get(dal, this.InstanceId.Value);
                if (el != null)
                {
                    this.LoadFields(el);
                    this.SelectedControlName = this.BuildSelectedControlString(el.ExpenseType.Template.EditControl);
                    this.TypeId = el.ExpenseType.Id;
                }
            }
        }

        protected void ddl_ExpenseTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.ddl_ExpenseTypes.SelectedValue.Equals(DDL_FIRST_ELEM))
                return;
            this.TypeId = new Guid(this.ddl_ExpenseTypes.SelectedValue);
  
            using (DataAccessLayer dal = new DataAccessLayer())
            {
                IQueryable<Template> temp = ExpenseType.GetTemplate(dal, this.TypeId.Value);
                Template template = temp.First<Template>();
                this.SelectedControlName = this.BuildSelectedControlString(template.EditControl);
            }
        }

        private String BuildSelectedControlString(String s)
        {
            return "~\\EditControls\\" + s;
        }

        private void SaveEditControlData()
        {
            if (string.IsNullOrEmpty(this.SelectedControlName))
            {
                return;
            }
            Type t = Page.LoadControl(this.SelectedControlName).GetType();
            IEnumerator phControls = this.ph_ControlHolder.Controls.GetEnumerator();
            while (phControls.MoveNext())
            {
                if (t == phControls.Current.GetType())
                {
                    IControlToLoadRW ictrw = (IControlToLoadRW)phControls.Current;
                    ictrw.Bind(this.InstanceId.Value, this.TypeId.Value);
                    ((IControlToLoadRW)phControls.Current).Save();

                }
            }
        }
        public void Save()
        {
            ExpenseLine expl = new ExpenseLine();
            String description = this.tb_description.Text;
            String justification = this.tb_Justification.Text;
            DateTime date = DateTime.Parse(this.tb_Date.Text);
            expl.ExpenseReportId = this.ExpenseReportId.Value;
            expl.Date = date;
            if (this.tb_Justification.Visible)
                expl.Justification = justification;
            if (this.InstanceId == null)
                this.InstanceId = Guid.NewGuid();
            expl.Id = this.InstanceId.Value;
            //o this.IdR pode ainda não estar bem se for clickado no botão de submit sem ter nenhum seleccionado
            expl.ExpenseTypeId = this.TypeId.Value;
            expl.Description = description;
            using (TransactionScope ts = new TransactionScope())
            {
                using (DataAccessLayer dal = new DataAccessLayer())
                {
                    expl.Save(dal);
                }
                this.SaveEditControlData();
                ts.Complete();
            }
        }

        private void LoadEditControl()
        {
            if (string.IsNullOrEmpty(this.SelectedControlName))
            {
                this.ph_ControlHolder.Controls.Clear();
                return;
            }
            //mal feito, devia ser carregado o tipo a partir da string para evitar este LoadControl
            Type t = Page.LoadControl(this.SelectedControlName).GetType();

            //se o controlo não for o selecionado é removido
            IEnumerator phControls = this.ph_ControlHolder.Controls.GetEnumerator();
            List<object> toRemove = new List<object>();
            while (phControls.MoveNext())
            {
                if (t != phControls.Current.GetType())
                    toRemove.Add(phControls.Current);
                else
                {
                    IControlToLoadRW ictlrw = ((IControlToLoadRW)(phControls.Current));
                    if (this.InstanceId.HasValue)
                        ictlrw.BindControls(this.InstanceId.Value);
                    ictlrw.BindType(this.TypeId.Value);
                    if (this.ReadOnly)
                        ictlrw.ReadOnly = true;
                    else
                        ictlrw.ReadOnly = false;
                }
            }
            foreach (object o in toRemove)
            {
                this.ph_ControlHolder.Controls.Remove((Control)o);
            }
        }

        //Ver nas configurações da parte comum o que tem que estar visível ou não
        private void LoadControlMetadata()
        {
            if (!this.TypeId.HasValue)
                return;
            using (DataAccessLayer dal = new DataAccessLayer())
            {
                ExpenseType expType = ExpenseType.Get(dal, this.TypeId.Value);
                if (expType.RequiresJust.Value)
                {
                    this.lb_Justification.Visible = true;
                    this.tb_Justification.Visible = true;
                }
                else
                {
                    this.lb_Justification.Visible = false;
                    this.tb_Justification.Visible = false;
                }
            }
        }

        private void SetFieldsReadOnly()
        {
            this.tb_description.Enabled = false;
            this.tb_Justification.Enabled = false;
            this.tb_Date.Enabled = false;
        }

        //aqui só deixo ficar aquele que está selecionado. Se não estiver nenhum selecionado não fica nenhum.
        protected override void OnPreRender(EventArgs ea)
        {
            base.OnPreRender(ea);

            if (this.ReadOnly)
            {
                this.SetFieldsReadOnly();
            }
            if (this.InstanceId.HasValue)
            {
                this.ddl_ExpenseTypes.Visible = false;
            }
            else
            {
                this.ddl_ExpenseTypes.Visible = true;
            }
            if (!this.InstanceId.HasValue && this.FirstAccess)
            {
                Context.Items["ToClear"] = "true";
                this.FirstAccess = false;
            }
            else
                Context.Items["ToClear"] = "false";
            this.DataBind();
            this.LoadControlMetadata();
            this.LoadEditControl();
        }
    }
}
